package com.xrui.ftp;

import org.apache.commons.configuration.*;
import org.apache.commons.configuration.tree.NodeCombiner;
import org.apache.commons.configuration.tree.UnionCombiner;

/**
 * Takes a Puppet-populated configuration file and generates two configuration
 * objects, one for Full settings and one for Incremental.
 */
public class FtpConfigurationPair {

    public final FtpConfiguration full;
    public final FtpConfiguration incremental;

    /**
     * Constructor
     * @param xmlConfigFilePath path to config file
     * @throws IllegalArgumentException Internal exceptions are wrapped by this, mostly to allow
     *         <code>static final</code> assignments which wouldn't be possible if it threw checked
     *         exceptions.
     */
    public FtpConfigurationPair(String xmlConfigFilePath) throws IllegalArgumentException {

        XMLConfiguration xmlConfig;
        try {
            xmlConfig = new XMLConfiguration(xmlConfigFilePath);
            Configuration common = xmlConfig.subset("shared");
            full = combine(common, requiredSubset(xmlConfig, "fullConfig"));
            incremental = combine(common, requiredSubset(xmlConfig, "incConfig"));
        } catch (ConfigurationException e) {
            throw new IllegalArgumentException(e.getMessage(), e);
        }
    }

    private static FtpConfiguration combine(Configuration common, Configuration additional) {
        NodeCombiner combiner = new UnionCombiner();
        CombinedConfiguration cc = new CombinedConfiguration(combiner);
        cc.addConfiguration((AbstractConfiguration) common, null, "ftpConfig");
        cc.addConfiguration((AbstractConfiguration) additional, null, "ftpConfig");
        return new FtpConfiguration(cc);
    }

    private static Configuration requiredSubset(XMLConfiguration config, String subsetName) throws ConfigurationException {
        Configuration subset = config.subset(subsetName);
        if (subset.isEmpty()) {
            throw new ConfigurationException("Configuration subset missing or empty: " + subsetName);
        }
        return subset;
    }
}
